﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Effects.GUI
{

    /// <summary>
    ///  Serializes instaces of <see cref="SettingsManagement"/>
    /// </summary>
    /// <remarks>
    ///  Class serializes and deserializes given instace of <see cref="SettingsManagement"/> class. This is the main logic of saving effect settings.
    /// </remarks>
    /// <seealso cref="SettingsManagement"/>
    public class SettingsSerializer
    {
        /// <summary>
        ///  Path to the file to write in
        /// </summary>
        private string fileName;

        /// <summary>
        ///  Creates new SettingsSerializer that writes to the given file.
        /// </summary>
        /// <param name="file"> Path to the file to write in.</param>
        public SettingsSerializer(string file)
        {
            this.fileName = file;
        }

        /// <summary>
        ///  Serialize SettingsManagement to file.
        /// </summary>
        /// <param name="settingsManagement"> SettingsManager to serialize </param>
        public void Serialize(SettingsManagement settingsManagement)
        {
            // open stream
            Stream stream = null;
            try
            {
                stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);

                // write header
                WriteHeader(stream);

                // serialize settingsManager
                BinaryFormatter formater = new BinaryFormatter();
                formater.Serialize(stream, settingsManagement);
            }
            catch (Exception )
            {
            }
            finally
            {
                if(stream != null)
                    stream.Close();
            }
        }

        /// <summary>
        ///  Deserialize EffectSettingsManager from file.
        /// </summary>
        /// <returns> Deserialized EffectSettingsManager or  null if any error occurred </returns>
        public SettingsManagement Deserialize()
        {
            Stream stream = null;
            try
            {
                stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);

                // check header of the file
                if (!ReadHeader(stream))
                    throw new SerializationException("Files header does not match expected format");

                BinaryFormatter formater = new BinaryFormatter();
                SettingsManagement settingsManagement = (SettingsManagement)formater.Deserialize(stream);
                return settingsManagement;
            }
            catch (Exception e)
            {
                return null;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }
        }

        /// <summary>
        ///  Reads header from the file and test it.
        /// </summary>
        /// <param name="stream"> Stream to read from </param>
        /// <returns> True if header fits, false if it doesn't </returns>
        private bool ReadHeader(Stream stream)
        {
            byte[] header = new byte[4];
            stream.Read(header, 0, 4);
            return (header[0] == 68 && header[1] == 69 && header[2] == 65 && header[3] == 78);
            //return (new string(header) == "DEAN");
        }

        /// <summary>
        ///  Writes header to the file
        /// </summary>
        /// <param name="stream"> Stream to write in. </param>
        private void WriteHeader(Stream stream)
        {
            stream.Write(new byte[] { 68, 69, 65, 78, }, 0, 4);
        }
    }
}
